import { KNumTable, KStrTable } from "@coldcloude/kai2";
import { EMPTY_FRAME_INFO, KKSpriteAnimeCollectionInfo, KKSpriteFrameInfo } from "@coldcloude/kakera";
import { Node, Sprite, SpriteAtlas } from "cc";

export class KKAnimeHub {
    animeMap = new KNumTable<KNumTable<[number,KKSpriteFrameInfo[]]>>();
    constructor(aniColle:KKSpriteAnimeCollectionInfo){
        const frameMap = new KStrTable<KKSpriteFrameInfo>();
        for(const frame of aniColle.frames){
            frameMap.set(frame.id,frame);
        }
        for(const anime of aniColle.animes){
            const frames:KKSpriteFrameInfo[] = [];
            for(const id of anime.frameIds){
                const frame = frameMap.get(id);
                if(frame){
                    frames.push(frame);
                }
                else{
                    frames.push(EMPTY_FRAME_INFO);
                }
            }
            this.animeMap.computeIfAbsent(anime.direction,()=>new KNumTable<[number,KKSpriteFrameInfo[]]>()).set(anime.action,[anime.duration,frames]);
        }
    }
    getAnime(direction:number,action:number):[number,KKSpriteFrameInfo[]]{
        let rst:[number,KKSpriteFrameInfo[]] = [0,[]];
        const actionMap = this.animeMap.get(direction);
        if(actionMap){
            const anime = actionMap.get(action);
            if(anime){
                rst = anime;
            }
        }
        return rst;
    }
}

export class KKAnimator {

    //config

    hub:KKAnimeHub;
    atlas:SpriteAtlas;

    //runtime

    spriteNode:Node;
    sprite:Sprite;

    direction:number = -1;
    action:number = -1;

    duration = 0;
    animeInfos:KKSpriteFrameInfo[] = undefined;

    time = 0;

    constructor(hub:KKAnimeHub,atlas:SpriteAtlas,spriteNode:Node,sprite:Sprite){
        this.hub = hub;
        this.atlas = atlas;
        this.spriteNode = spriteNode;
        this.sprite = sprite;
    }

    setDirectionAction(param:{
        direction?: number,
        action?: number
    }){
        let directionChanged = false;
        let actionChanged = false;
        if(param.action!==undefined&&param.action!==this.action){
            this.action = param.action;
            actionChanged = true;
        }
        if(param.direction!==undefined&&param.direction!==this.direction){
            this.direction = param.direction;
            directionChanged = true;
        }
        if(actionChanged||directionChanged){
            [this.duration,this.animeInfos] = this.hub.getAnime(this.direction,this.action);
            if(actionChanged){
                this.time = 0;
            }
        }
    }
    
    setHub(hub:KKAnimeHub){
        this.hub = hub;
        //save
        const direction = this.direction;
        const action = this.action;
        //reset
        this.direction = -1;
        this.action = -1;
        this.duration = 0;
        this.animeInfos = undefined;
        this.time = 0;
        //build
        this.setDirectionAction({direction:direction,action:action});
    }
    
    setAtlas(atlas:SpriteAtlas){
        this.atlas = atlas;
    }

    render(dt:number){
        this.time += dt*1000;
        if(this.duration>0&&this.animeInfos&&this.animeInfos.length>0){
            const t = (Math.floor(this.time)|0)%(this.duration|0);
            const index = Math.floor(t/this.duration*this.animeInfos.length)|0;
            if(index>=0&&index<this.animeInfos.length){
                const info = this.animeInfos[index];
                this.sprite.spriteFrame = this.atlas.getSpriteFrame(info.id);
                this.spriteNode.setPosition(info.positionX,info.positionY);
            }
        }
    }
}
